{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import copy\n",
    "\n",
    "from functools import partial\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import numpy.random as rnd\n",
    "\n",
    "from alns import ALNS, State\n",
    "from alns.criteria import HillClimbing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "SEED = 5432"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# The cutting-stock problem\n",
    "\n",
    "The [cutting-stock problem (CSP)](https://en.wikipedia.org/wiki/Cutting_stock_problem) is well-known problem in operations research. In simple terms, it asks how many pieces of material are needed to cut an ordered amount of differently-sized beams, such that the wastage is minimised. Many different formulations exist, e.g. for the one-, two-, and even three-dimensional case. Here we solve an instance of the one-dimensional problem, obtained from the data [here](http://www.math.tu-dresden.de/~capad/cpd-ti.html#1D). It is known that the optimal solution for this problem requires the use of only 74 beams."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "OPTIMAL_BEAMS = 74"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Each available beam is of length: 1000\n",
      "Number of beams to be cut (orders): 180\n"
     ]
    }
   ],
   "source": [
    "# The first line lists the number of lines for beam orders.\n",
    "# The second line is the length of the available beams. Each\n",
    "# following line is an order of (length, amount) tuples.\n",
    "with open('640.csp') as file:\n",
    "    data = file.readlines()\n",
    "\n",
    "NUM_LINES = int(data[0])\n",
    "BEAM_LENGTH = int(data[1])\n",
    "\n",
    "# Beams to be cut from the available beams\n",
    "BEAMS = [int(length)\n",
    "         for datum in data[-NUM_LINES:]\n",
    "         for length, amount in [datum.strip().split()]\n",
    "         for _ in range(int(amount))]\n",
    "\n",
    "print(\"Each available beam is of length:\", BEAM_LENGTH)\n",
    "print(\"Number of beams to be cut (orders):\", len(BEAMS))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Operators and solution state\n",
    "\n",
    "To use the ALNS meta-heuristic, we need to have destroy and repair operators that work on a proposed solution, and a way to describe such a solution in the first place. The ALNS package exposes the class ``State`` to describe a solution, with an ``objective()`` member that computes this solution's objective value. Using it, we may compute a simple initial solution, and then apply the ALNS algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Solution state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class CspState(State):\n",
    "    \"\"\"\n",
    "    Solution state for the CSP problem. It has two data members, assignments\n",
    "    and unassigned. Assignments is a list of lists, one for each beam in use.\n",
    "    Each entry is another list, containing the ordered beams cut from this \n",
    "    beam. Each such sublist must sum to at most BEAM_LENGTH. Unassigned is a\n",
    "    list of ordered beams that are not currently assigned to one of the\n",
    "    available beams.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, assignments, unassigned=None):\n",
    "        self.assignments = assignments\n",
    "        self.unassigned = []\n",
    "        \n",
    "        if unassigned is not None:\n",
    "            self.unassigned = unassigned\n",
    "\n",
    "    def copy(self):\n",
    "        \"\"\"\n",
    "        Helper method to ensure each solution state is immutable.\n",
    "        \"\"\"\n",
    "        return CspState(copy.deepcopy(self.assignments),\n",
    "                        self.unassigned.copy())\n",
    "\n",
    "    def objective(self):\n",
    "        \"\"\"\n",
    "        Computes the total number of beams in use.\n",
    "        \"\"\"\n",
    "        return len(self.assignments)\n",
    "\n",
    "    def plot(self):\n",
    "        \"\"\"\n",
    "        Helper method to plot a solution.\n",
    "        \"\"\"\n",
    "        _, ax = plt.subplots(figsize=(12, 6))\n",
    "\n",
    "        ax.barh(np.arange(len(self.assignments)), \n",
    "                [sum(assignment) for assignment in self.assignments], \n",
    "                height=1)\n",
    "\n",
    "        ax.set_xlim(right=BEAM_LENGTH)\n",
    "        ax.set_yticks(np.arange(len(self.assignments), step=10))\n",
    "\n",
    "        ax.margins(x=0, y=0)\n",
    "\n",
    "        ax.set_xlabel('Usage')\n",
    "        ax.set_ylabel('Beam (#)')\n",
    "\n",
    "        plt.draw_if_interactive()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def wastage(assignment):\n",
    "    \"\"\"\n",
    "    Helper method that computes the wastage on a given beam assignment.\n",
    "    \"\"\"\n",
    "    return BEAM_LENGTH - sum(assignment)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Destroy operators\n",
    "\n",
    "We will consider two simple destroy operators, **random_removal** and **worst_removal**. Random removal randomly removes currently assigned beams, whereas worst removal removes those beams that are currently cut with the most waste. Both remove a fixed percentage of the current solution state, controlled by a degree of destruction parameter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "degree_of_destruction = 0.25\n",
    "\n",
    "def beams_to_remove(num_beams):\n",
    "    return int(num_beams * degree_of_destruction)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def random_removal(state, random_state):\n",
    "    \"\"\"\n",
    "    Iteratively removes randomly chosen beam assignments.\n",
    "    \"\"\"\n",
    "    state = state.copy()\n",
    "\n",
    "    for _ in range(beams_to_remove(state.objective())):\n",
    "        idx = random_state.randint(state.objective())\n",
    "        state.unassigned.extend(state.assignments.pop(idx))\n",
    "\n",
    "    return state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def worst_removal(state, random_state):\n",
    "    \"\"\"\n",
    "    Removes beams in decreasing order of wastage, such that the\n",
    "    poorest assignments are removed first.\n",
    "    \"\"\"\n",
    "    state = state.copy()\n",
    "\n",
    "    # Sort assignments by wastage, worst first\n",
    "    state.assignments.sort(key=wastage, reverse=True)\n",
    "\n",
    "    # Removes the worst assignments\n",
    "    for _ in range(beams_to_remove(state.objective())):\n",
    "        state.unassigned.extend(state.assignments.pop(0))\n",
    "\n",
    "    return state"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Repair operators\n",
    "\n",
    "We define two equally simple repair operators, **greedy_insert** and **minimal_wastage**. The first considers each currently unassigned ordered beam, and finds the first beam this order may be inserted into. The second does something similar, but finds a beam where its insertion would result in the smallest beam wastage."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def greedy_insert(state, random_state):\n",
    "    \"\"\"\n",
    "    Inserts the unassigned beams greedily into the first fitting\n",
    "    beam. Shuffles the unassigned ordered beams before inserting.\n",
    "    \"\"\"\n",
    "    random_state.shuffle(state.unassigned)\n",
    "\n",
    "    while len(state.unassigned) != 0:\n",
    "        beam = state.unassigned.pop(0)\n",
    "\n",
    "        for assignment in state.assignments:\n",
    "            if beam <= wastage(assignment):\n",
    "                assignment.append(beam)\n",
    "                break\n",
    "        else:\n",
    "            state.assignments.append([beam])\n",
    "\n",
    "    return state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def minimal_wastage(state, random_state):\n",
    "    \"\"\"\n",
    "    For every unassigned ordered beam, the operator determines\n",
    "    which beam would minimise that beam's waste once the ordered\n",
    "    beam is inserted.\n",
    "    \"\"\"\n",
    "    def insertion_cost(assignment, beam):  # helper method for min\n",
    "        if beam <= wastage(assignment):\n",
    "            return wastage(assignment) - beam\n",
    "\n",
    "        return float(\"inf\")\n",
    "\n",
    "    while len(state.unassigned) != 0:\n",
    "        beam = state.unassigned.pop(0)\n",
    "\n",
    "        assignment = min(state.assignments,\n",
    "                         key=partial(insertion_cost, beam=beam))\n",
    "\n",
    "        if beam <= wastage(assignment):\n",
    "            assignment.append(beam) \n",
    "        else:\n",
    "            state.assignments.append([beam])\n",
    "\n",
    "    return state"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Initial solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initial solution has objective value: 81\n"
     ]
    }
   ],
   "source": [
    "rnd_state = rnd.RandomState(SEED)\n",
    "\n",
    "state = CspState([], BEAMS.copy())\n",
    "initial_solution = greedy_insert(state, rnd_state)\n",
    "\n",
    "print(\"Initial solution has objective value:\", initial_solution.objective())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "initial_solution.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Heuristic solution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "alns = ALNS(rnd_state)\n",
    "\n",
    "alns.add_destroy_operator(random_removal)\n",
    "alns.add_destroy_operator(worst_removal)\n",
    "\n",
    "alns.add_repair_operator(greedy_insert)\n",
    "alns.add_repair_operator(minimal_wastage)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "criterion = HillClimbing()\n",
    "\n",
    "result = alns.iterate(initial_solution, [3, 2, 1, 0.5], 0.8, criterion,\n",
    "                      iterations=5000, collect_stats=True)\n",
    "\n",
    "solution = result.best_state\n",
    "\n",
    "objective = solution.objective()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtEAAAGDCAYAAADtZ0xmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XmYZHV97/H3hxlwQMVhGY0IChokCblm1BFxISGARhQlIS5gjOsVr3GJXo1rrrgmhmjUmMXgnqgoIESiRiVRXCM6ICAoqCjIojAom4LI8r1/nFMzNWVVV9XQp7um5/16nn66z6k653yrTk/Pp3/9Pb+TqkKSJEnS5LZa7AIkSZKkzY0hWpIkSZqSIVqSJEmakiFakiRJmpIhWpIkSZqSIVqSJEmakiFa0qJI8uokH5jj8XOT7N/BcTvZ76Ya9z4sNUlOTfK/J3zufknO77qmMTW8Ism7FrMGSbPJEC2pE0memuSbSa5P8uMk/5xk5aTbV9XeVXXqbazhfUleP9/7XQqmCbOLpaq+WFV79ZaTXJjkoK6Ol2T/JJcM1PBXVTXT75OkxWGIljTvkrwI+BvgL4A7AfsC9wBOSbLNYtamLVMa/p8nad74A0XSvEqyPfAa4HlV9amquqmqLgQeTxOkn9T39BVJPpLkuiRnJPmdvv2sH3VMslWSlyW5IMlPkhyXZMe+5z40yVeSXJ3k4nYU/EjgT4CXJPlZkv/o32+SXZLcMLCf+ya5MsnW7fLTk3w7yVVJPp3kHiNe86eSPHdg3VlJDmu/fltb17VJTk+y34j9/MpI6DTvw8B2OyT5eJJ1bf0fT7Jr+9gbgP2Af2jfm38YsY99+97Xs/rbYJI8rX1vrkvy/STPGtj20CRntq/5giSP6Hv4Hkm+3G77mSQ7j3s/kvwbcHfgP9qaXzJBjacmeUOSLwPXA/ccVXeS2wP/CezS7v9n7ffIRu02SR6TpiXo6nb/vzlwrl6c5Owk17Tf2yuGvTZJmz9DtKT59mBgBXBi/8qq+hlNSHlY3+pDgeOBHYEPAf/eC7ADng/8IfB7wC7AVcA/AiS5e7vftwOrgNXAmVV1DPBB4OiqukNVPXqgnsuA/wH+uG/1E4ETquqmJH8IvAI4rN3vF4FjR7zmDwFH9BaS/BbNLwyfaFd9va2r9zqP38RwNfJ9GGIr4L1tHXcHbgD+AaCqXtm+nue2781zBzdOcre2/te3db8Y+GiSVe1TrgAOAbYHnga8Jcn92m33Af6V5i8RK4HfBS7s2/0T223uDGzT7ntOVfWnwA+BR7c1Hz1BjQB/ChwJ3BG4aFTdVfVz4GDgsnb/d2i/R/rfk3vTfA+8gOZ74pM0ob7/ryuPBx4B7AHcB3jquNcmafNkiJY033YGrqyqm4c89qP28Z7Tq+qEqroJ+Dua8L3vkO2eBbyyqi6pqhuBVwOPTbKcZrT5v6rq2HbU+ydVdeaEta4Pv0kCHN6u6x3zr6vq2+1r+Stg9YjR6JMGHvsT4MS2VqrqA21dN1fVm4HbAXsN2c84c70PG2mP99Gqur6qrgPeQBO+J/Uk4JNV9cmqurWqTgHWAo9s9/+JqrqgGp8HPkMzug3wDOA9VXVKu+2lVXVe377fW1XfqaobgONofsHYFHPW2HpfVZ3bvvc3jal7nCcAn2hf103Am4BtaX5x7Pn7qrqsqn4K/MdteG2SZpwhWtJ8uxLYeViwA+7aPt5zce+LqroVuIRmhHXQPYCT2j+hXw18G7gFuAuwG3DBJtZ6AvCgJLvQjJYWzQht75hv6zvmT4EAdxvcSRtSP0ETwmk/f7D3eJIXtS0E17T7uhMb/zIxqbneh40k2S7JvyS5KMm1wBeAlUmWTXGsx/WO1R7voTTnkCQHJ/lqkp+2jz2y7zWNOyc/7vv6euAOE9Y0VY2ti/s3GFP3OLvQjGYD679nL2bj74n5em2SZpwhWtJ8+x/gRpo2iPXantODgf/uW71b3+NbAbsCG/0JvXUxcHBVrez7WFFVl7aP3WtELTVXoVV1Nc1I5ONpWgyOrareNhcDzxo45rZV9ZURuzsWOCLJg2hGJz/Xvq79gJe2x9ihqlYC19AE8kE/B7brLbSBt781Ya73YdCLaEa7H1hV29P8kkDfced8b9pj/dvAsW5fVW9McjvgozQjsXdpX9Mn+/Y91zm5LQZrHlnjsG0mqHvce3IZTXDv7S8038PD3n9JS5whWtK8qqpraC4sfHuSRyTZOsnuNL3PlwD/1vf0+yc5rB21fgFN+P7qkN2+A3hDr10iyaokh7aPfRA4KMnjkyxPslOS3p/QLwfuOabkDwFPpumN/lDf+ncAL0+yd3vMOyV53Bz7+SRNwHot8JF2lBKaXtybgXXA8iSvounHHeY7NBdbPqrtDf9LmtaP/ppGvQ+D7kjTB311mosPjxp4fNx78wHg0Un+IMmyJCvaC/12peljvl37mm5OcjDw8L5t3w08LcmBaS6GvFuS35jjWJMarHmuGocZV/flwE5J7jRi++OAR7Wva2uaX1RuBEb9YiVpCTNES5p3VXU0zUV5bwKuBU6jGTU8sNcn3PoYTZ/pVTQXgB3W9poOehtwMvCZJNfRBO0Htsf6Ic2f5F9E03JxJtCb5ePdwG+1f+r/9xHlngzsCVxeVWf1vYaTaKbp+3DbDnEOzUj6qNd8I83FlAexcRj/NM2Fj9+haQX4BQMtBn37uAb4M+BdNKObP6f5xWPs+zDEW2lGxK9sn/epgcffRtNPfVWSvx9Sy8U0F36+giZ0XkxzoeBWbfvK82lC5VU0o/gn9237NdqL9mhG3T9P3wjubfDXwF+25/PFc9U4bOMJ6j6P5i8K32+PscvA9ufT9GG/neZ9fTTNhY6/nIfXJmkzkw1/uZSk2ZHkh8CTquoLi12LJEmDHImWNHPaKcpWsfG0aJIkzQxDtKSZkuQBwHeBt7etGpIkzRzbOSRJkqQpORItSZIkTckQLUmSJE1p2B3FZs7OO+9cu++++2KXIUmSpCXu9NNPv7KqVo173mYRonfffXfWrl272GVIkiRpiUty0STPs51DkiRJmpIhWpIkSZqSIVqSJEmakiFakiRJmpIhWpIkSZqSIVqSJEmakiFakiRJmpIhWpIkSZqSIVqSJEmaUqchOskLk5yb5JwkxyZZkeS5Sb6XpJLs3OXxJUmSpC50FqKT3A14PrCmqn4bWAYcDnwZOAiY6JaKkiRJ0qzpup1jObBtkuXAdsBlVfWNqrqw4+PeZj++5hd87vwruOGXtyx2KZIkSZoxnYXoqroUeBPwQ+BHwDVV9ZlJt09yZJK1SdauW7euqzJH+soFV/K0936dK677xYIfW5IkSbOty3aOHYBDgT2AXYDbJ3nSpNtX1TFVtaaq1qxataqrMiVJkqSpddnOcRDwg6paV1U3AScCD+7weJ2oWuwKJEmSNGu6DNE/BPZNsl2SAAcC3+7wePMqWewKJEmSNKu67Ik+DTgBOAP4ZnusY5I8P8klwK7A2Une1VUNkiRJUheWd7nzqjoKOGpg9d+3H5IkSdJmyTsWjmFLtCRJkgYZokcINkVLkiRpOEO0JEmSNCVD9BjlHHeSJEkaYIgewSnuJEmSNIohWpIkSZqSIXoMmzkkSZI0yBAtSZIkTckQLUmSJE3JED2Gk3NIkiRpkCF6hDg9hyRJkkYwREuSJElTMkSPZT+HJEmSNmaIHsFmDkmSJI1iiJYkSZKmZIiWJEmSpmSIHsMp7iRJkjTIED2CM9xJkiRpFEO0JEmSNCVD9Bh2c0iSJGmQIXqEOMmdJEmSRjBES5IkSVMyRI/h7BySJEkaZIgewdk5JEmSNIohWpIkSZqSIXqMcn4OSZIkDTBEj2A3hyRJkkYxREuSJElTMkRLkiRJUzJEj+EUd5IkSRpkiB7BKe4kSZI0iiFakiRJmpIhegzbOSRJkjTIED2S/RySJEkazhAtSZIkTckQPYZ3LJQkSdIgQ/QIzs4hSZKkUQzRkiRJ0pQM0WM4O4ckSZIGGaJHsJtDkiRJo3QaopO8MMm5Sc5JcmySFUn2SHJaku8m+UiSbbqsQZIkSZpvnYXoJHcDng+sqarfBpYBhwN/A7ylqvYErgKe0VUNkiRJUhe6budYDmybZDmwHfAj4ADghPbx9wN/2HENmyROzyFJkqQROgvRVXUp8CbghzTh+RrgdODqqrq5fdolwN26qkGSJEnqQpftHDsAhwJ7ALsAtwcOHvLUofNfJDkyydoka9etW9dVmZIkSdLUumznOAj4QVWtq6qbgBOBBwMr2/YOgF2By4ZtXFXHVNWaqlqzatWqDsucm1PcSZIkaVCXIfqHwL5JtkvTYHwg8C3gc8Bj2+c8BfhYhzVsMjuiJUmSNEqXPdGn0VxAeAbwzfZYxwAvBf5vku8BOwHv7qoGSZIkqQvLxz9l01XVUcBRA6u/D+zT5XHnUw1v2ZYkSdIWzDsWjuAMd5IkSRrFEC1JkiRNyRA9hrNzSJIkaZAhegTbOSRJkjSKIVqSJEmakiF6DLs5JEmSNMgQPUK83YokSZJGMERLkiRJUzJEj1FOzyFJkqQBhuhR7OaQJEnSCIZoSZIkaUqGaEmSJGlKhugx7IiWJEnSIEP0CLZES5IkaRRDtCRJkjQlQ/QYznAnSZKkQYboERIbOiRJkjScIVqSJEmakiF6LPs5JEmStDFD9Ag2c0iSJGkUQ7QkSZI0JUP0GM7OIUmSpEGG6BGcnEOSJEmjGKIlSZKkKRmiJUmSpCkZosewJVqSJEmDDNEjxEnuJEmSNIIhWpIkSZqSIXoMp7iTJEnSIEP0CE5xJ0mSpFEM0ZIkSdKUDNFjlP0ckiRJGmCIHsFuDkmSJI1iiJYkSZKmZIgew2YOSZIkDTJEj2I/hyRJkkYwREuSJElTMkSP4eQckiRJGmSIHiH2c0iSJGkEQ7QkSZI0JUO0JEmSNKXOQnSSvZKc2fdxbZIXJPmdJP+T5JtJ/iPJ9l3VMB/KSe4kSZI0oLMQXVXnV9XqqloN3B+4HjgJeBfwsqr6X+3yX3RVw20RW6IlSZI0wkK1cxwIXFBVFwF7AV9o158C/PEC1bBJLvrJ9YtdgiRJkmbMQoXow4Fj26/PAR7Tfv04YLdhGyQ5MsnaJGvXrVu3ACVu7C7brwDgKxf8ZMGPLUmSpNnWeYhOsg1NaD6+XfV04DlJTgfuCPxy2HZVdUxVramqNatWreq6zF+xx8635y7b346tl9nXIUmSpI0tX4BjHAycUVWXA1TVecDDAZLcG3jUAtSwSbZe5uQlkiRJ+lULkRKPYEMrB0nu3H7eCvhL4B0LUMOmc3IOSZIkDeg0RCfZDngYcGLf6iOSfAc4D7gMeG+XNdwWztAhSZKkYTpt56iq64GdBta9DXhbl8edTw5ES5IkaZBNv3MIocoYLUmSpI0ZoudgO4ckSZKGMUSP4Ti0JEmSBhmi5xDAbg5JkiQNMkTPIfZzSJIkaQhD9BgOREuSJGnQRCE6ybZJ9uq6mFnjOLQkSZKGGRuikzwaOBP4VLu8OsnJXRc2K5ziTpIkSYMmGYl+NbAPcDVAVZ0J7N5dSTMktnNIkiTpV00Som+uqms6r2QG2c4hSZKkYSa57fc5SZ4ILEuyJ/B84CvdljVDHIqWJEnSgElGop8H7A3cCBwLXAu8oMuiZkUSyhQtSZKkAWNHoqvqeuCV7ccWxXYOSZIkDTM2RCf5HEOaGqrqgE4qmjFOziFJkqRBk/REv7jv6xXAHwM3d1PObPGGhZIkSRpmknaO0wdWfTnJ5zuqZ+Y4Ei1JkqRBk7Rz7Ni3uBVwf+DXOqtohgQvLJQkSdKvmqSd43SanujQtHH8AHhGl0XNCts5JEmSNMwk7Rx7LEQhs8p2DkmSJA0aGaKTHDbXhlV14vyXM3vM0JIkSRo010j0o+d4rIAlH6JjP4ckSZKGGBmiq+ppC1nIrLKdQ5IkSYMmubCQJI+iufX3it66qnptV0XNimYc2hQtSZKkjW017glJ3gE8AXgeTa58HHCPjuuaCXZzSJIkaZixIRp4cFU9Gbiqql4DPAjYrduyZoftHJIkSRo0SYi+of18fZJdgJuALWLaO0eiJUmSNMwkPdEfT7IS+FvgDJom4Xd2WtUMcSBakiRJgya52crr2i8/muTjwIqquqbbsmZDCGU/hyRJkgZMcmHhWUlekeReVXXjlhKgwXYOSZIkDTdJT/RjgJuB45J8PcmLk9y947pmhuPQkiRJGjQ2RFfVRVV1dFXdH3gicB/gB51XNgOCs3NIkiTpV016s5XdgcfTzBd9C/CS7kqaIfZzSJIkaYixITrJacDWwHHA46rq+51XNUMciJYkSdKgSUain1JV53VeyQxyHFqSJEnDTNITvUUG6B6nuJMkSdKgSWbn2GLZEi1JkqRhDNFzMENLkiRpmElutrJdkv+X5J3t8p5JDum+tNlgN4ckSZIGTTIS/V7gRuBB7fIlwOs7q2iGJKGcn0OSJEkDJgnR96qqo4GbAKrqBraQToct4kVKkiRpapOE6F8m2ZZ2yuQk96IZmZ5Tkr2SnNn3cW2SFyRZneSr7bq1Sfa5ja+hU7ZzSJIkadAk80S/GvgUsFuSDwIPAZ46bqOqOh9YDZBkGXApcBLwTuA1VfWfSR4JHA3svwm1d87ZOSRJkjTM2BBdVZ9JcjqwL02Hw59X1ZVTHudA4IKquihJAdu36+8EXDblvhbUTbfcutglSJIkacZMctvvk4FjgZOr6uebeJzD230AvAD4dJI30bSTPHgT99m5WwtOv+gqvn7hT3nA7jsudjmSJEmaEZP0RL8Z2A/4VpLjkzw2yYpJD5BkG+AxwPHtqmcDL6yq3YAXAu8esd2Rbc/02nXr1k16uHn15AfdA4BLr7phUY4vSZKk2TTJbb8/X1V/BtwTOAZ4PHDFFMc4GDijqi5vl58CnNh+fTww9MLCqjqmqtZU1ZpVq1ZNcbj5c59dVza1OM2dJEmS+kx0x8J2do4/Bv4P8ADg/VMc4wg2tHJA0wP9e+3XBwDfnWJfC6p3XaEzdEiSJKnfJD3RHwEeSDNDxz8Cp1bVRFfbJdkOeBjwrL7VzwTelmQ58AvgyGmLXijOziFJkqRhJpni7r3AE6vqlml3XlXXAzsNrPsScP9p97WYHImWJElSv5EhOskBVfVZYDvg0AwMy1bViUM3XELiPQslSZI0xFwj0b8HfBZ49JDHig0XBy55DkRLkiSp38gQXVVHtV++tqp+0P9Ykj06rWpG9Abfy34OSZIk9Zlkdo6PDll3wnwXIkmSJG0u5uqJ/g1gb+BOSQ7re2h7YOKbrSwFjkNLkiSp31w90XsBhwAr2bgv+jqaaeqWvPXXUpqiJUmS1GeunuiPAR9L8qCq+p8FrGlmDM5IIkmSJMFkPdH/J8nK3kKSHZK8p8OaZo63/ZYkSVK/SUL0farq6t5CVV0F3Le7kmaH49CSJEkaZpIQvVWSHXoLSXZksjsdLhnOcCdJkqR+k4ThNwNfSXICzSV2jwfe0GlVM2L9PNGLW4YkSZJmzNgQXVX/mmQtcABNh8NhVfWtziubAd72W5IkScNM0s4BsCPw86p6O7BuS7ljYY/tHJIkSeo3NkQnOQp4KfDydtXWwAe6LGpWbGjnMEVLkiRpg0lGov8IeAzwc4Cqugy4Y5dFzQqbOSRJkjTMJCH6l1VVtNfXJbl9tyXNHts5JEmS1G+SEH1ckn8BViZ5JvBfwDu7LWtGOBQtSZKkISaZneNNSR4GXAvsBbyqqk7pvLIZ4kC0JEmS+k1005Q2NG9RwRn6prizn0OSJEl9RrZzJPlS+/m6JNcO+fhBkj9buFIXXmznkCRJ0hAjR6Kr6qHt56EzcSTZCfgK8E/dlDY7HIeWJElSv4naOZLcD3goTZ78UlV9o6p+kmT/LotbbL2BaLs5JEmS1G+Sm628Cng/sBOwM/C+JH8JUFU/6ra8xRX7OSRJkjTEJCPRRwD3rapfACR5I3AG8PouC5sl5VC0JEmS+kwyT/SFwIq+5dsBF3RSzYxxHFqSJEnDjByJTvJ2mh7oG4Fzk5zSLj8M+NLClDcbHIeWJElSv7naOda2n08HTupbf2pn1cyYOE20JEmShphrirv3AyRZAfw6zYDsBb3e6C1BbOiQJEnSEHPdbGV5kqOBS2hm5/gAcHGSo5NsvVAFzgIHoiVJktRvrgsL/xbYEdijqu5fVfcF7gWsBN60EMUtuvXtHMZoSZIkbTBXiD4EeGZVXddbUVXXAs8GHtl1YbPAaaIlSZI0zFwhumrIEGxV3YIdDpIkSdqCzRWiv5XkyYMrkzwJOK+7kmaHt/2WJEnSMHNNcfcc4MQkT6eZ5q6ABwDbAn+0ALUtOm/7LUmSpGHmmuLuUuCBSQ4A9qYZmP3PqvrvhSpuVpTdK5IkSeoz10g0AFX1WeCzC1DLzHEcWpIkScPM1ROtlj3RkiRJ6meInsP6234vbhmSJEmaMYboOXjbb0mSJA1jiJ6A7RySJEnqZ4iew4Z2DlO0JEmSNhg7O8emSrIX8JG+VfcEXgU8CNirXbcSuLqqVndVhyRJkjTfOgvRVXU+sBogyTLgUuCkqnpr7zlJ3gxc01UN88V2DkmSJPVbqHaOA4ELquqi3oo0twN8PHDsAtUwtV47x7u++H3KJC1JkqTWQoXow/nVsLwfcHlVfXfYBkmOTLI2ydp169Z1XuAwW2/VvD1XXX8TP/35LxelBkmSJM2ezkN0km2AxwDHDzx0BHOMQlfVMVW1pqrWrFq1qssSR9pqq/C6Q/cG4FYHoiVJktTqrCe6z8HAGVV1eW9FkuXAYcD9F+D4t02cK1qSJEkbW4h2jmEjzgcB51XVJQtw/HnhNHeSJEnq6TREJ9kOeBhw4sBDw3qkZ9L6cWgztCRJklqdtnNU1fXATkPWP7XL484nuzkkSZI0yDsWTsiBaEmSJPUYoscIDkVLkiRpY4boCXmvFUmSJPUYosfo9UQ7O4ckSZJ6DNFj2MwhSZKkQYboCdnOIUmSpB5D9Bgb2jkkSZKkhiF6DGfnkCRJ0iBD9ITKfg5JkiS1DNHjOBAtSZKkAYboCTkQLUmSpB5D9BgOREuSJGmQIXqMxBgtSZKkjRmiJ2Q7hyRJknoM0WP0xqG97bckSZJ6DNFj2M0hSZKkQYboCdnOIUmSpB5D9BiOREuSJGmQIXpCDkRLkiSpxxA9RtpLC73ttyRJknoM0WPYziFJkqRBhugJOQ4tSZKkHkP0hOzmkCRJUo8hegxv+y1JkqRBhuiJORQtSZKkhiF6DMehJUmSNMgQPSF7oiVJktRjiB6j1xJthpYkSVKPIXqM2NAhSZKkAYboCdnOIUmSpB5D9Bgb2jlM0ZIkSWoYosewmUOSJEmDDNETsp1DkiRJPYboMda3cxiiJUmS1DJEj2VDhyRJkjZmiJ6QFxZKkiSpxxA9RhyIliRJ0gBD9ITsiZYkSVKPIXoMB6IlSZI0yBA9RuznkCRJ0oDOQnSSvZKc2fdxbZIXtI89L8n5Sc5NcnRXNcwn2zkkSZLUs7yrHVfV+cBqgCTLgEuBk5L8PnAocJ+qujHJnbuqYT70xqGdnUOSJEk9C9XOcSBwQVVdBDwbeGNV3QhQVVcsUA2bpNfNcasZWpIkSa2FCtGHA8e2X98b2C/JaUk+n+QBC1TDJlm+rHmLvvTddYtciSRJkmZF5yE6yTbAY4Dj21XLgR2AfYG/AI7LkKv3khyZZG2StevWLV6AXb3bSgBut3zZotUgSZKk2bIQI9EHA2dU1eXt8iXAidX4GnArsPPgRlV1TFWtqao1q1atWoAyh1u2VZPv7YmWJElSz0KE6CPY0MoB8O/AAQBJ7g1sA1y5AHVskvUXFpqhJUmS1Oo0RCfZDngYcGLf6vcA90xyDvBh4ClVsxtRnSZakiRJgzqb4g6gqq4HdhpY90vgSV0etwszm/IlSZK04Lxj4RhpGzpmd6xckiRJC80QPYbtHJIkSRpkiJ6Qs3NIkiSpxxA9Ids5JEmS1GOIliRJkqZkiB7DnmhJkiQNMkSPEUzRkiRJ2pghekIzfD8YSZIkLTBD9Bi9dg4ztCRJknoM0WPYzCFJkqRBhugJORAtSZKkHkP0GIm3/ZYkSdLGDNGSJEnSlAzRY/R6or3ttyRJknoM0WM4O4ckSZIGGaIlSZKkKRmix1h/YeEi1yFJkqTZYYiWJEmSpmSInpRN0ZIkSWoZoieQ2M4hSZKkDQzRkiRJ0pQM0RMIdnNIkiRpA0P0BJJ4sxVJkiStZ4iWJEmSpmSInoDtHJIkSepniJ6As3NIkiSpnyFakiRJmpIhegIhtnNIkiRpPUO0JEmSNCVD9CSCU9xJkiRpPUP0BAJeWShJkqT1DNGSJEnSlAzRE3CKO0mSJPUzRE+gmZ3DGC1JkqSGIVqSJEmakiF6Aom3/ZYkSdIGhugJmaElSZLUY4ieQBa7AEmSJM0UQ/QEEm/7LUmSpA0M0ZIkSdKUDNETCN72W5IkSRss72rHSfYCPtK36p7Aq4CVwDOBde36V1TVJ7uqY144O4ckSZL6dBaiq+p8YDVAkmXApcBJwNOAt1TVm7o6tiRJktSlzkL0gAOBC6rqomTzm+siwMfP/hFnXXL1YpciSZK05P3a9iv45yfdf7HLmNNChejDgWP7lp+b5MnAWuBFVXXV4AZJjgSOBLj73e++IEWO8tQH7843LjZAS5IkLYTttlmoiLrpUh03+ybZBrgM2LuqLk9yF+BKmvuXvA64a1U9fa59rFmzptauXdtpnZIkSVKS06tqzbjnLcTsHAcDZ1TV5QBVdXlV3VJVtwLvBPZZgBokSZKkebMQIfoI+lo5kty177E/As5ZgBokSZKkedNpw0mS7YCHAc/qW310ktU07RwXDjwmSZIkzbxOQ3RVXQ/sNLDuT7s8piRJktQ171goSZIkTckQLUmSJE3JEC1JkiRNyRAtSZIkTckQLUmSJE3JEC1JkiRNyRAtSZIkTckQLUmSJE3JEC1JkiRNKVW12DWMlWQdcNEiHHpn4MpFOK4Wlud5y+B53jJ4npc+z/GWYTHP8z2qatW4J20WIXqxJFlbVWsWuw51y/O8ZfA8bxk8z0swWC4BAAAHpklEQVSf53jLsDmcZ9s5JEmSpCkZoiVJkqQpGaLndsxiF6AF4XneMnietwye56XPc7xlmPnzbE+0JEmSNCVHoiVJkqQpGaJHSPKIJOcn+V6Sly12PZpOkvckuSLJOX3rdkxySpLvtp93aNcnyd+35/rsJPfr2+Yp7fO/m+Qpi/FaNFyS3ZJ8Lsm3k5yb5M/b9Z7nJSTJiiRfS3JWe55f067fI8lp7Tn7SJJt2vW3a5e/1z6+e9++Xt6uPz/JHyzOK9IoSZYl+UaSj7fLnuMlJsmFSb6Z5Mwka9t1m+3PbEP0EEmWAf8IHAz8FnBEkt9a3Ko0pfcBjxhY9zLgv6tqT+C/22VozvOe7ceRwD9D8w8bOAp4ILAPcFTvH7dmws3Ai6rqN4F9gee0/049z0vLjcABVfU7wGrgEUn2Bf4GeEt7nq8CntE+/xnAVVX168Bb2ufRfm8cDuxN87Phn9qf9Zodfw58u2/Zc7w0/X5Vre6bvm6z/ZltiB5uH+B7VfX9qvol8GHg0EWuSVOoqi8APx1YfSjw/vbr9wN/2Lf+X6vxVWBlkrsCfwCcUlU/raqrgFP41WCuRVJVP6qqM9qvr6P5z/dueJ6XlPZ8/axd3Lr9KOAA4IR2/eB57p3/E4ADk6Rd/+GqurGqfgB8j+ZnvWZAkl2BRwHvapeD53hLsdn+zDZED3c34OK+5Uvaddq83aWqfgRNAAPu3K4fdb79PthMtH/OvS9wGp7nJaf9M/+ZwBU0/2FeAFxdVTe3T+k/Z+vPZ/v4NcBOeJ5n3VuBlwC3tss74Tleigr4TJLTkxzZrttsf2YvX4yDbgYyZJ3TmCxdo8633webgSR3AD4KvKCqrm0GpIY/dcg6z/NmoKpuAVYnWQmcBPzmsKe1nz3Pm5kkhwBXVNXpSfbvrR7yVM/x5u8hVXVZkjsDpyQ5b47nzvx5diR6uEuA3fqWdwUuW6RaNH8ub/8URPv5inb9qPPt98GMS7I1TYD+YFWd2K72PC9RVXU1cCpND/zKJL2BoP5ztv58to/fiaa1y/M8ux4CPCbJhTTtkwfQjEx7jpeYqrqs/XwFzS/E+7AZ/8w2RA/3dWDP9srgbWguVDh5kWvSbXcy0LuK9ynAx/rWP7m9Enhf4Jr2T0qfBh6eZIf2ooWHt+s0A9oeyHcD366qv+t7yPO8hCRZ1Y5Ak2Rb4CCa/vfPAY9tnzZ4nnvn/7HAZ6u5IcLJwOHtzA570Fys9LWFeRWaS1W9vKp2rardaf6//WxV/Qme4yUlye2T3LH3Nc3P2nPYjH9m284xRFXdnOS5NCdlGfCeqjp3kcvSFJIcC+wP7JzkEpored8IHJfkGcAPgce1T/8k8Eiai1CuB54GUFU/TfI6ml+qAF5bVYMXK2rxPAT4U+Cbbb8swCvwPC81dwXe386ysBVwXFV9PMm3gA8neT3wDZpfqGg//1uS79GMTh4OUFXnJjkO+BbNzC7PadtENLteiud4KbkLcFLbcrcc+FBVfSrJ19lMf2Z7x0JJkiRpSrZzSJIkSVMyREuSJElTMkRLkiRJUzJES5IkSVMyREuSJElTMkRLkiRJUzJES1LHkvys/bx7kifO875fMbD8lXnc91uT/O7Auj9I8ur2Rgef7Ft/SJLXzNexJWnWGaIlaeHsDkwVotubjMxloxBdVQ+esqZRx90R2LeqvjDw0H7AF4HfBb7ct/4TNLdu3m4+ji9Js84QLUkL543AfknOTPLCJMuS/G2Sryc5O8mzAJLsn+RzST4EfLNd9+9JTk9ybpIj23VvBLZt9/fBdl1v1Dvtvs9J8s0kT+jb96lJTkhyXpIPtrdQH/RY4FO9hSRPaO8M+XzgrcA7gaclORmgve3yqcAh8/+2SdLs8bbfkrRwXga8uKoOAWjD8DVV9YAktwO+nOQz7XP3AX67qn7QLj+9vd3ttsDXk3y0ql6W5LlVtXrIsQ4DVgO/A+zcbtMbVb4vsDdwGc1o8kOALw1s/xDghN5CVX0kyfHAl6rqwUk+CxxaVdf1bbOWZqT6uKnfGUnazDgSLUmL5+HAk9sR3tOAnYA928e+1hegAZ6f5Czgq8Bufc8b5aHAsVV1S1VdDnweeEDfvi+pqluBM2naTAbdFVg3sG5P4IL26+0GAjTAFcAuY+qSpCXBkWhJWjwBnldVn95oZbI/8POB5YOAB1XV9UlOBVZMsO9Rbuz7+haG/19wQ/8xkqylGdFenuRbwF3b8P+8qvpi+7QV7XaStOQ5Ei1JC+c64I59y58Gnp1ka4Ak905y+yHb3Qm4qg3QvwHs2/fYTb3tB3wBeELbd72K5kLAr01R67eBX+8tVNUamosHDwWOBl5ZVav7AjTAvYFzpjiGJG22DNGStHDOBm5OclaSFwLvAr4FnJHkHOBfGD4q/CmaEeCzgdfRtHT0HAOc3buwsM9J7fHOAj4LvKSqfjxFrZ8A9h9Ydz+a9o/9aNpDBv1+u50kLXlpLqiWJGljSb4EHFJVV0/w3LsAH6qqA7uvTJIWnyFakjRUkgcCN1TV2RM89wHATVV1ZveVSdLiM0RLkiRJU7InWpIkSZqSIVqSJEmakiFakiRJmpIhWpIkSZqSIVqSJEma0v8Ht5SaFo4fxNAAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "_, ax = plt.subplots(figsize=(12, 6))\n",
    "result.plot_objectives(ax=ax)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Having obtained a reasonable solution, we now want to investigate each operator's performance. This may be done via the `plot_operator_counts()` method on the `result` object, like below. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Qy688MINyzSzlsFDs8xsi5WVleUMHjx4aFlZmZYuXZr/9NNPz4bkS9x7773XbsqUKe9EBKNGjdrlmWee6bh48eK8nj17rn/ppZfeg6QXoEuXLhV33HFHj5dffnl2r169Wswp/Ybum5tvvnneUUcd1X7mzJkzYNNhPzfddFPXoqKiimnTpr1TWlqqffbZZ/DRRx+9EmDKlCkdJk6cOH3w4MHrmm+LG8/999/feeTIkSt23333ss6dO1e8+uqrBQsWLMh76qmnths/fvzMTp06VS5evDgX4JRTTul3ySWXLDrttNOWr1mzRhUVFaptH/fv33/d3Llz2911111zDzvssNUnnXRS3xtvvLHb1VdfvTjzGFy4cGHedddd1+uVV16ZXVhYWHnFFVf0vOaaa3pcffXViy644IK+zz333Kxdd9217Kijjurf3PuqKZSXlzN27NhO3//+95dC7cfsEUccsapqntrqdOvWrfymm27q9frrr8/s1atX+eLFi3N79OhRMWrUqOVHHXXUijPPPHMZwAEHHDDw7rvv/nC33XYre/HFFzuce+65O77xxhuzzzvvvB3POuusTy644IJPf/nLJRbxKQAABn9JREFUX9bZQ2Nm2xYnIma2xaqGcgA8//zzHc4888x+s2fPnv6Pf/yj8JVXXikcOnToUIA1a9bkzJw5s92hhx5acsUVV+xw7rnn9j7mmGNWHH744as2v4ZtV0P3Tf/+/TebRDz//POFM2fOLHj88ce3AygpKcmdMWNGuzZt2sTuu+++uqUkIQAPPfRQ8YUXXrgE4IQTTvhszJgxxZWVlXznO9/ZcA1Hjx49KpYtW5azePHiNqeddtpygIKCggBic/u4Z8+e6w477LDVAN/97nc/vfXWW7sDizPX/9JLL3V4//332+27776DAdavX68RI0asmjRpUrs+ffqU7bbbbmUAp5566qejR49uMV+Oq5Ln+fPntxk2bNiaY489diVAbfszMxGprc6ECRNyjj766GVVJxl69OixyTUnK1asyJk4cWLHk046aeeqsnXr1glgwoQJHZ955pn3Ac4555xPr7nmmi0a/mlmWycnImbWKEaNGrV62bJleQsXLsyLCC666KKFP/nJT5ZWrzdhwoQZjz76aNEVV1zR+/nnn1950003LWyOeLOpPvtm1qxZbWqbHyAidPPNN390wgknrMwsf/LJJzsVFBQ0zUX+zWDRokW5b7zxRuHs2bPbX3DBBVRUVEhSHHnkkcslbVQ3oua7V29uH1dfRvXnVfMffPDBK5944okPMstfe+219jXVbymqkudPP/0097DDDtvl+uuv737llVcu2dz7uUptda699trukjZ7m/GKigo6depUXpW4V+fblJu1XL5GxMwaxcSJE9tVVlbSo0eP8iOOOGLlmDFjulaNq//ggw/y58+fnzd37tz8Tp06VZ533nmfXXTRRYsnTZpUANChQ4eKqrotUX32TVFRUcXq1as37IOioqKKVatW5VY9/+pXv7rijjvu6FZWViaAKVOmtF25cmWL22djxozZ7vjjj/90wYIFU+fPnz910aJFU/r06bOuuLi4fMyYMV1LSkpyABYvXpxbXFxc2bNnz3VjxozpDFBaWqqSkpKc2vYxwMKFC9s8//zzHQD+/Oc/Fx944IGrYONjcOTIkavHjRvXcdq0aW0BSkpKcqZMmdJ2+PDha+fNm9em6jqUBx54ICsX0mdbly5dKm699daPfve73/UoKyvT5vZnldrqHH744Ssff/zx4kWLFuVC0m4AHTt2rKg6fouLiyv79Omz7t57790OoLKyktdff709wF577bXqnnvuKQa45557umRrH5hZdrhHxKyFqM/tdhtb1VAOSM6I3nHHHXPz8vI4/vjjV06fPr3dPvvsMxigoKCg8v777/9g5syZbX/605/2ycnJIS8vL26//fYPAU4//fSlRxxxxIDu3buvf/PNN2c3eqD1uN1uY2vovtl1113LRowYsWrAgAG7HnLIIStuvfXW+Xl5eTFo0KChp5xyytIrr7xyydy5c9vutttuQyJCxcXF659++un3m3o76nu73cby8MMPd7n00ks36iU75phjlr3zzjvtjjjiiOXDhw8fkp+fH6NGjVpx2223zf/Tn/70wdlnn73TNddcs31+fn48/PDD79e2j/Py8qJ///5r77333i7nnXfeTv369Su75JJLPoFNj8G77rpr7sknn9y/aojQz3/+8/m777572W9/+9sPjzrqqF2Ki4vL99tvv1XvvPNOk9z5qT63221KBx10UOmQIUNKR48evd3555//WU37s3fv3uVVPUS17fO999577Y9//OOFX/rSlwbn5OTEsGHD1jz66KNzTz311M/OPffcvnfeeWePRx555P2//OUvc84+++ydbrjhhl7l5eU67rjjPjvggANKb7/99o9OPvnk/rfffnuPb3zjG8uacZeYWRNQbV3bZrZ1mzx58tw99tij1qESZraxWbNmtTnqqKMGvPvuu9ObO5aWYNGiRbl77bXX0AULFkxt7lgmT57cdY899ujb3HGYWcO0uG59MzMza1pz587N33///Yecf/75i+uubWZWMw/NMjOzVmHQoEHr3BvSOPr27bt+7ty505o7DjPbtrlHxGzbVVlZWdlyb+FjZlYP6edgi7lznFlr4kTEbNs17ZNPPilyMmJmrVVlZaU++eSTIsC9M2bbIA/NMttGlZeXn7Vo0aLRixYtGoZPKphZ61QJTCsvLz+ruQMxs4bzXbPMzMzMzCzrfBbVzMzMzMyyzomImZmZmZllnRMRMzMzMzPLuv8P10rM+H/rvW0AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 864x432 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "figure = plt.figure(\"operator_counts\", figsize=(12, 6))\n",
    "figure.subplots_adjust(bottom=0.15, hspace=.5)\n",
    "result.plot_operator_counts(figure=figure, title=\"Operator diagnostics\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Several conclusions follow,\n",
    "\n",
    "* The destroy operators are about equally good, so there is little to be gained changing these around.\n",
    "* The repair operators, however, are not created equal: the `minimal_wastage` operator is significantly better than the simple `greedy_insert`. This makes intuitive sense, as minimising wastage exploits the assignment structure much better than a simple insertion heuristic does. It follows that the `greedy_insert` operator is actually not all that useful, and may be dropped from the ALNS heuristic altogether."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Heuristic solution has objective value: 75\n"
     ]
    }
   ],
   "source": [
    "print(\"Heuristic solution has objective value:\", solution.objective())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtoAAAF3CAYAAACbhOyeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAGbZJREFUeJzt3X3QZmV9H/Dvr7ugri8LqFACdtC4kjCmgm4pVusYUItZI6TVVJOmm4SEmdY2WpNRdDI1SWNmnTi+dLROqS/ZJFZFfIEmjmazYtK0SrOINSgalKxKQCCCoKJS8Nc/7oNu1ofdZ8lz3ffzPPv5zDxz7nOdt989nDn75bqvc051dwAAgJX19xZdAAAArEeCNgAADCBoAwDAAII2AAAMIGgDAMAAgjYAAAwgaAMAwACCNgAADCBoAwDAAII2AAAMsHHRBSzHhk2be+PmYxddBgAAa8SPnLD5kLe54oor/qa7H75SNayJoL1x87E5fvvrFl0GAABrxJ4d2w55m6r6wkrWYOgIAAAMIGgDAMAAgjYAAAwgaAMAwACCNgAADCBoAwDAAII2AADryt778Gi/EQRtAAAYQNAGAIABBG0AABhA0AYAgAEEbQAAGEDQBgCAAYYF7ao6uao+sc/f7VX1oqo6pqp2VdU10/ToUTUAAMCiDAva3f3Z7j61u09N8oQkdyR5X5ILkuzu7i1Jdk/zAACwrsxr6MhZST7f3V9Ick6SnVP7ziTnzqkGAADWudXysppkfkH7eUneMX0+rrtvSJJpeuycagAAgLkZHrSr6sgkz07y7kPc7vyq2lNVe+6+47YxxQEAwCDz6NF+ZpKPd/eN0/yNVXV8kkzTm5baqLsv7O6t3b11w6bNcygTAABWzjyC9vPzvWEjSXJpku3T5+1JLplDDQAAMFdDg3ZVbUry9CTv3ad5R5KnV9U107IdI2sAAIBF2Dhy5919R5KH7tf2lcyeQgIAAOuWN0MCAMAAgjYAAAwgaAMAwACCNgAADCBoAwDAAII2AAAMMPTxfgAAjLF3x7ZFl8BB6NEGAIABBG0AABhA0AYAgAGM0QYAWINOuuAPF13CqrFax6vr0QYAgAEEbQAAGEDQBgCAAQRtAAAYwM2QAACsiNV6U+Ki6NEGAIABBG0AABhA0AYAgAGM0QYAYEV4ic7fpkcbAAAGELQBAGAAQRsAAAYwRhsAgFVnEc/krlet7P70aAMAwACCNgAADCBoAwDAAII2AAAM4GZIAABWnaVefrOIGyT/LvRoAwDAAII2AAAMIGgDAMAAxmgDAHCfrLUx0/OmRxsAAAYQtAEAYIChQbuqjqqqi6vqM1V1dVU9saqOqapdVXXNND16ZA0AALAIo3u0X5/kg939Q0kel+TqJBck2d3dW5LsnuYBAGBdGXYzZFU9JMlTkvxsknT3nUnurKpzkjx1Wm1nko8keemoOgAAWFluglyekT3aj0pyc5K3VdWVVfXmqnpgkuO6+4YkmabHDqwBAAAWYmTQ3pjk8Une1N2nJflGDmGYSFWdX1V7qmrP3XfcNqpGAAAYYmTQvi7Jdd19+TR/cWbB+8aqOj5JpulNS23c3Rd299bu3rph0+aBZQIAwMobNka7u79cVV+qqpO7+7NJzkry6elve5Id0/SSUTUAALDyTrrgDxddwrIseiz56DdD/vskb6+qI5Ncm+TnMutFv6iqzkvyxSTPHVwDAADM3dCg3d2fSLJ1iUVnjTwuAAAsmjdDAgDAAKOHjgAAwELsP5Z83mO29WgDAMAAgjYAAAwgaAMAwACCNgAADOBmSAAAFm7RL5cZQY82AAAMIGgDAMAAgjYAAAxgjDYAAAu3/8tl1gM92gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADDAxpE7r6q9Sb6W5O4kd3X31qo6Jsm7kpyUZG+Sn+zuW0fWAQAA8zaPHu0f7e5Tu3vrNH9Bkt3dvSXJ7mkeAADWlUUMHTknyc7p884k5y6gBgAAGGp00O4kf1RVV1TV+VPbcd19Q5JM02MH1wAAAHM3dIx2kid19/VVdWySXVX1meVuOAXz85Nkw0MePqo+AAAYYmiPdndfP01vSvK+JKcnubGqjk+SaXrTvWx7YXdv7e6tGzZtHlkmAACsuGFBu6oeWFUPvudzkmckuSrJpUm2T6ttT3LJqBoAAGBRRg4dOS7J+6rqnuP89+7+YFX9eZKLquq8JF9M8tyBNQAAwEIMC9rdfW2Sxy3R/pUkZ406LgAArAbeDAkAAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADCNoAADCAoA0AAAMI2gAAMICgDQAAAwjaAAAwgKANAAADbFzuilV1dJIfSPLNJHu7+zvDqgIAgDXugEG7qjYneUGS5yc5MsnNSe6f5Liq+liS/9Ldlw2vEgAA1piD9WhfnOR3k/zT7v7qvguq6glJfqaqHtXdbxlVIAAArEUHDNrd/fQDLLsiyRUrXhEAAKwDy7oZsqrOHl0IAACsJwcM2lV1elVtSPJb+7T93vCqAABgjTtYj/bzk/xJkkdV1auq6qeSPP5QDlBVG6rqyqr6g2n+kVV1eVVdU1Xvqqoj71vpAACweh0saL+0u5+c5ItJ/jDJMUn+flV9rKretcxjvDDJ1fvMvyrJa7t7S5Jbk5x3iDUDAMCK2rtj24rv82BB+0NVtSvJw5M8NMkHknyhu89I8ssH23lVnZhkW5I3T/OV5MzMnmaSJDuTnHvfSgcAgNXrgEG7u380ybOTfD3JDyb5zSSPrqr3J3neMvb/uiQvSXLPy20emuSr3X3XNH9dkhPuQ90AALCqHfSpI939zSRf6u5Xd/dPJfl8kl9M8lcH2q6qnpXkpukxgN9tXuoQ97L9+VW1p6r23H3HbQcrEwAAVpVlvYK9u8/cZ/YN3X1zkvccZLMnJXl2Vf1YZm+TfEhmPdxHVdXGqVf7xCTX38sxL0xyYZLc7/gtS4ZxAABYrZb1HO19LfctkN39su4+sbtPymyYyYe7+6eTXJbkOdNq25Nccqg1AADAanew52j/j6r68ao6Yollj6qq36iqnz/EY740yYur6nOZjdn2+nYAANadgw0d+cUkL07yuqq6JcnNmQ0DOSmzsdpv6O6D9kh390eSfGT6fG2S0+9zxQAAsAYcMGh395cze2rIS6rqpCTHJ/lmkr/s7juGVwcAAGvUsm6GTJLu3ptk77BKAABgHTnkmyEBAICDE7QBAGAAQRsAAAZYVtCuqmdV1ZVVdUtV3V5VX6uq20cXBwAAa9Vyb4Z8XZJ/nuQvuttbGgEA4CCWO3TkS0muErIBAGB5ltuj/ZIkH6iqP0ny7Xsau/s1Q6oCAIA1brlB+5VJvp7ZWyGPHFcOAACsD8sN2sd09zOGVgIAAOvIcsdo/3FVCdoAALBMyw3aL0jywar6psf7AQDAwS1r6Eh3P3h0IQAAsJ4sd4x2quroJFsyuyEySdLdfzqiKAAAWOuWFbSr6heSvDDJiUk+keSMJB9Ncua40gAAYO1a7hjtFyb5R0m+0N0/muS0JDcPqwoAANa45Qbtb3X3t5Kkqu7X3Z9JcvK4sgAAYG1b7hjt66rqqCTvT7Krqm5Ncv24sgAAYG1b7lNHfmL6+GtVdVmSzUk+OKwqAABY4w7lqSNPTrKlu99WVQ9PckKSvxpWGQAArGHLGqNdVa9I8tIkL5uajkjy+6OKAgCAtW65N0P+RJJnJ/lGknT39Um8xAYAAO7FcoP2nd3dSTpJquqB40oCAID52btj25D9LjdoX1RV/zXJUVX1i0n+OMl/G1IRAACsA8t96sirq+rpSW7P7PnZ/7G7dw2tDAAA1rBlP3VkCta7quphSb4yriQAAFj7Djh0pKrOqKqPVNV7q+q0qroqyVVJbqyqs+dTIgAArD0H69F+Q5KXZ/aCmg8neWZ3f6yqfijJO+KlNQAAsKSD3Qy5sbv/qLvfneTL3f2xJOnuz4wvDQAA1q6DBe3v7PP5m/st6xWuBQAA1o2DDR15XFXdnqSSPGD6nGn+/kMrAwCANeyAQbu7N8yrEAAAWE+W+8IaAADgEAwL2lV1/6r6P1X1f6vqU1X161P7I6vq8qq6pqreVVVHjqoBAAAWZWSP9reTnNndj0tyapKzq+qMJK9K8tru3pLk1iTnDawBAAAWYljQ7pmvT7NHTH+d5MwkF0/tO5OcO6oGAABYlKFjtKtqQ1V9IslNSXYl+XySr3b3XdMq1yU5YWQNAACwCEODdnff3d2nJjkxyelJfnip1ZbatqrOr6o9VbXn7jtuG1kmAACsuLk8daS7v5rkI0nOSHJUVd3zWMETk1x/L9tc2N1bu3vrhk2b51EmAACsmJFPHXl4VR01fX5AkqcluTrJZUmeM622Pcklo2oAAIBFOdibIf8ujk+ys6o2ZBboL+ruP6iqTyd5Z1X9ZpIrk7xlYA0AALAQw4J2d38yyWlLtF+b2XhtAABYt7wZEgAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGCAYa9gBwCA1Wzvjm1D969HGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwCAw87eHduGH0PQBgCAAQRtAAAYQNAGAIABBG0AABhA0AYAgAEEbQAAGEDQBgCAAQRtAAAYQNAGAIABBG0AABhA0AYAgAGGBe2qekRVXVZVV1fVp6rqhVP7MVW1q6qumaZHj6oBAAAWZWSP9l1Jfrm7fzjJGUleUFWnJLkgye7u3pJk9zQPAADryrCg3d03dPfHp89fS3J1khOSnJNk57TaziTnjqoBAAAWZS5jtKvqpCSnJbk8yXHdfUMyC+NJjp1HDQAAME/Dg3ZVPSjJe5K8qLtvP4Ttzq+qPVW15+47bhtXIAAADDA0aFfVEZmF7Ld393un5hur6vhp+fFJblpq2+6+sLu3dvfWDZs2jywTAABW3MinjlSStyS5urtfs8+iS5Nsnz5vT3LJqBoAAGB/e3dsm8txNg7c95OS/EySv6iqT0xtL0+yI8lFVXVeki8mee7AGgAAYCGGBe3u/rMkdS+Lzxp1XAAAWA28GRIAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwCAw8beHdvmdixBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAgMPCPG+ETARtAAAYQtAGAIABBG0AABhA0AYAgAEEbQAAGEDQBgCAAQRtAAAYQNAGAIABBG0AABhA0AYAgAEEbQAAGEDQBgCAAQRtAADWvb07ts39mII2AAAMMCxoV9Vbq+qmqrpqn7ZjqmpXVV0zTY8edXwAAFikkT3av5Pk7P3aLkiyu7u3JNk9zQMAwLozLGh3958muWW/5nOS7Jw+70xy7qjjAwBAspjx2cn8x2gf1903JMk0PXbOxwcAgLlYtTdDVtX5VbWnqvbcfcdtiy4HAAAOybyD9o1VdXySTNOb7m3F7r6wu7d299YNmzbPrUAAAFgJ8w7alybZPn3enuSSOR8fAIDDyKLGZydjH+/3jiQfTXJyVV1XVecl2ZHk6VV1TZKnT/MAALDubBy14+5+/r0sOmvUMQEAYLVYtTdDAgDAWiZoAwDAAII2AAAMIGgDAMAAgjYAAAwgaAMAwACCNgAADCBoAwDAAII2AAAMIGgDAMAAgjYAAAwgaAMAwACCNgAADCBoAwDAAII2AAAMIGgDALAu7d2xbaHHF7QBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGAAQRsAAAYQtAEAYABBGwAABhC0AQBgAEEbAAAGELQBAGCAhQTtqjq7qj5bVZ+rqgsWUQMAAIw096BdVRuSvDHJM5OckuT5VXXKvOsAAGD92rtj26JLWEiP9ulJPtfd13b3nUnemeScBdQBAADDLCJon5DkS/vMXze1AQDAurGIoF1LtPX3rVR1flXtqao9d99x2xzKAgCAlbOIoH1dkkfsM39ikuv3X6m7L+zurd29dcOmzXMrDgAAVkJ1f19n8tgDVm1M8pdJzkry10n+PMlPdfenDrDN15J8dj4VsoY8LMnfLLoIVh3nBUtxXrAU5wX7O7m7H7xSO9u4Ujtaru6+q6r+XZIPJdmQ5K0HCtmTz3b31vHVsZZU1R7nBftzXrAU5wVLcV6wv6ras5L7m3vQTpLu/kCSDyzi2AAAMA/eDAkAAAOslaB94aILYFVyXrAU5wVLcV6wFOcF+1vRc2LuN0MCAMDhYK30aAMAwJqyqoN2VZ1dVZ+tqs9V1QWLrof5qapHVNVlVXV1VX2qql44tR9TVbuq6pppevTUXlX1n6dz5ZNV9fjFfgNGqqoNVXVlVf3BNP/Iqrp8Oi/eVVVHTu33m+Y/Ny0/aZF1M05VHVVVF1fVZ6brxhNdL6iq/zD9G3JVVb2jqu7venH4qaq3VtVNVXXVPm2HfH2oqu3T+tdU1fblHHvVBu2q2pDkjUmemeSUJM+vqlMWWxVzdFeSX+7uH05yRpIXTP/9L0iyu7u3JNk9zSez82TL9Hd+kjfNv2Tm6IVJrt5n/lVJXjudF7cmOW9qPy/Jrd396CSvndZjfXp9kg929w8leVxm54frxWGsqk5I8ktJtnb3YzN7pPDz4npxOPqdJGfv13ZI14eqOibJK5L84ySnJ3nFPeH8QFZt0M7sS3yuu6/t7juTvDPJOQuuiTnp7hu6++PT569l9o/mCZmdAzun1XYmOXf6fE6S3+2ZjyU5qqqOn3PZzEFVnZhkW5I3T/OV5MwkF0+r7H9e3HO+XJzkrGl91pGqekiSpyR5S5J0953d/dW4XjB7jPEDppflbUpyQ1wvDjvd/adJbtmv+VCvD/8sya7uvqW7b02yK98f3r/Pag7aJyT50j7z101tHGamn+9OS3J5kuO6+4ZkFsaTHDut5nw5fLwuyUuSfGeaf2iSr3b3XdP8vv/tv3teTMtvm9ZnfXlUkpuTvG0aUvTmqnpgXC8Oa93910leneSLmQXs25JcEdcLZg71+nCfrhurOWgv9X+RHpFymKmqByV5T5IXdfftB1p1iTbnyzpTVc9KclN3X7Fv8xKr9jKWsX5sTPL4JG/q7tOSfCPf+xl4Kc6Lw8D0s/45SR6Z5AeSPDCzYQH7c71gX/d2Htyn82M1B+3rkjxin/kTk1y/oFpYgKo6IrOQ/fbufu/UfOM9P/FO05umdufL4eFJSZ5dVXszG052ZmY93EdNPw0nf/u//XfPi2n55nz/z4esfdclua67L5/mL84seLteHN6eluSvuvvm7v5/Sd6b5J/E9YKZQ70+3KfrxmoO2n+eZMt0d/CRmd3AcOmCa2JOpnFxb0lydXe/Zp9Flya5507f7Uku2af9X093C5+R5LZ7fhJi/ejul3X3id19UmbXhA93908nuSzJc6bV9j8v7jlfnjOtr4dqnenuLyf5UlWdPDWdleTTcb043H0xyRlVtWn6N+We88L1guTQrw8fSvKMqjp6+rXkGVPbAa3qF9ZU1Y9l1lu1Iclbu/uVCy6JOamqJyf5n0n+It8bi/vyzMZpX5TkH2R2EX1ud98yXUTfkNmNCXck+bnu3jP3wpmbqnpqkl/p7mdV1aMy6+E+JsmVSf5Vd3+7qu6f5PcyG+N/S5Lndfe1i6qZcarq1MxukD0yybVJfi6zziTXi8NYVf16kn+Z2ZOsrkzyC5mNq3W9OIxU1TuSPDXJw5LcmNnTQ96fQ7w+VNXPZ5ZFkuSV3f22gx57NQdtAABYq1bz0BEAAFizBG0AABhA0AYAgAEEbQAAGEDQBgCAAQRtgFWsqk6qqqv2a/u1qvqVRdUEwPII2gAAMICgDbBGVdUvVdWnq+qTVfXOqe30qvrfVXXlND15at9UVRdN676rqi6vqq3TsmdU1Uer6uNV9e6qetAivxfAerFx0QUAcJ9dkOSR01vtjpraPpPkKd19V1U9LclvJfkXSf5tklu7+x9W1WOTfCJJquphSX41ydO6+xtV9dIkL07yG/P+MgDrjaANsLrd2+t7O8knk7y9qt6f2euEk2Rzkp1VtWVa54ip/clJXp8k3X1VVX1yaj8jySlJ/tfszcM5MslHV/pLAByODB0BWN2+kuTo/dqOSfI3SbYleWOSJyS5oqo2JvlPSS7r7scm+fEk95+2qXvZfyXZ1d2nTn+ndPd5K/0lAA5HgjbAKtbdX09yQ1WdlSRVdUySs5P8WZJHdPdlSV6S5KgkD8qsR/uvp81/dp9d/VmSn5z2cUqSH5naP5bkSVX16GnZpqp6zMjvBHC4qO57+1USgNVgCsZvzPd6tn87yUVJLsssWFeS3+/uHVX1xCQ7k9yc5MNJfqa7T6qqB07tj0lyZZLHJnled19TVWcmeVWS+037/9XuvnQ+3w5g/RK0AQ4DVbUhyRHd/a2q+sEku5M8prvvXHBpAOuWmyEBDg+bklxWVUdk1gP+b4RsgLH0aAMAwABuhgQAgAEEbQAAGEDQBgCAAQRtAAAYQNAGAIABBG0AABjg/wOyzjfReXg5ugAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "solution.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of beams used is 75, which is 1 more than the optimal value, which was 74.\n"
     ]
    }
   ],
   "source": [
    "print(\"Number of beams used is {0}, which is {1} more than the optimal value, which was {2}.\"\n",
    "      .format(solution.objective(), solution.objective() - OPTIMAL_BEAMS, OPTIMAL_BEAMS))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conclusions\n",
    "\n",
    "In the code above we implement a simple ALNS-based heuristic for the CSP. Although the operators are simple and few, we do find very good results in limited time: we require just one more beam than optimal solution does, a result that is **1.35%** above optimal.\n",
    "\n",
    "This notebook offers another case where the ALNS library may be put to use to construct powerful, efficient heuristic pipelines from simple, locally greedy operators."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
